package com.htfyun.ft.agingtest;

import android.content.Context;
import android.text.TextUtils;

import com.htfyun.ft.FTApplication;
import com.htfyun.ft.R;
import com.htfyun.ft.common.FTUtils;
import com.htfyun.ft.utils.DebugLog;
import com.htfyun.ft.utils.FileReadWrite;
import com.htfyun.ft.utils.TimeStringUtils;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import androidx.annotation.NonNull;

public enum AgingTestItemAttr {

    sleep(4, "sleep", R.string.aging_test_item_sleep, true, AgingTestConstants.DEFAULT_SLEEP_COUNT, TestSleep.class),
    reboot(2, "reboot", R.string.aging_test_item_reboot, true, AgingTestConstants.DEFAULT_REBOOT_COUNT, TestReboot.class),
    hardware(3, "hardware", R.string.aging_test_item_hardware, false, AgingTestConstants.DEFAULT_HARDWARE_TEST_TIME, TestHardware.class),
    emmc_cpu(1, "emmc_cpu", R.string.aging_test_item_emmc_cpu, true, AgingTestConstants.DEFAULT_EMMC_CPU_COUNT, TestEmmcCpu.class),
    ;

    private final int id;
    private final String name;
    private final int nominalRes;
    private boolean isCountForTestOver;//true, 次数计算; false, 时间计算
    private long defaultTimes;
    private final Class<? extends AgingTestItemBase> itemCls;

    private AgingTestItemAttr(int id, String name, int nominalRes,
                              boolean isCountForTestOver, long defaultTimes,
                              Class<? extends AgingTestItemBase> cls) {
        this.id = id;
        this.name = name;
        this.nominalRes = nominalRes;
        this.isCountForTestOver = isCountForTestOver;
        this.defaultTimes = defaultTimes;
        this.itemCls = cls;
    }


    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getNominalRes() {
        return nominalRes;
    }

    public String getNominalName() {
        final Context context = FTApplication.getContext();

        return context.getString(getNominalRes());
    }

    public Class<? extends AgingTestItemBase> getItemCls() {
        return itemCls;
    }

    public boolean isCountForTestOver() {
        return isCountForTestOver;
    }

    public long getDefaultTimes() {
        return defaultTimes;
    }

    public String getDetail() {

        if (isForceTestOver()) {
            return "";
        }

        final Context context = FTApplication.getContext();

        if (isCountForTestOver) {
            return getNominalName() + context.getString(R.string.aging_test_item_requested_count,
                    getTimesOfTestOver());

        } else {
            long time = getTimesOfTestOver();
            if (time < 0) {
                time = 0;
            }
            return getNominalName() + context.getString(R.string.aging_test_item_requested_time,
                    TimeStringUtils.makeTimeString(time));
        }
    }

    public String getTestDetail() {

        if (isForceTestOver()) {
            return "";
        }

        final Context context = FTApplication.getContext();

        if (isCountForTestOver) {
            return getNominalName() + context.getString(R.string.aging_test_item_count, getTestCount());
        } else {
            return getNominalName() + context.getString(R.string.aging_test_item_time,
                    TimeStringUtils.makeTimeString(getExitTime_ms() - getStartTime_ms()));
        }
    }

    public void setLog(String log) {
        AgingSharedPreference.setString(getName() + "_log", log);
    }

    public String getLog() {
        return AgingSharedPreference.getString(getName() + "_log");
    }

    public void setErrorLog(String log) {
        AgingSharedPreference.setString(getName() + "_error_log", log);
    }

    public String getErrorLog() {
        return AgingSharedPreference.getString(getName() + "_error_log");
    }

    public long getStartTime_ms() {

        return AgingSharedPreference.getLong(getName() + "_start_time", 0);

    }

    public void setStartTime_ms(long ms) {

        AgingSharedPreference.setLong(getName() + "_start_time", ms);

    }

    public long getExitTime_ms() {

        return AgingSharedPreference.getLong(getName() + "_exit_time", 0);

    }

    public void setExitTime_ms(long ms) {

        AgingSharedPreference.setLong(getName() + "_exit_time", ms);

    }

    /**
     * 开始测试的绝对时间, 相对于格力时间
     */
    public long getStartTimeAbsolute_ms() {

        return AgingSharedPreference.getLong(getName() + "_start_time_absolute", System.currentTimeMillis());

    }

    public void setStartTimeAbsolute_ms(long ms) {

        AgingSharedPreference.setLong(getName() + "_start_time_absolute", ms);

    }

    public long getExitTimeAbsolute_ms() {

        return AgingSharedPreference.getLong(getName() + "_exit_time_absolute", System.currentTimeMillis());

    }

    public void setExitTimeAbsolute_ms(long ms) {

        AgingSharedPreference.setLong(getName() + "_exit_time_absolute", ms);

    }

    public long getTimesOfTestOver() {

        return AgingSharedPreference.getLong(getName() + "_times_of_test_over", getDefaultTimes());

    }

    //次数或者时间
    public void setTimesOfTestOver(long times) {

        AgingSharedPreference.setLong(getName() + "_times_of_test_over", times);

    }

    public int getTestCount() {

        return AgingSharedPreference.getInt(getName() + "_test_count", 0);

    }

    public void setTestCount(int count) {

        AgingSharedPreference.setInt(getName() + "_test_count", count);

    }

    public void addOneTestCount() {
        int cnt = getTestCount();
        setTestCount(cnt + 1);
    }

    public boolean isForceTestOver() {

        return AgingSharedPreference.getBoolean(getName() + "_force_test_over", false);

    }

    public void setForceTestOver(boolean forceOver) {

        AgingSharedPreference.setBoolean(getName() + "_force_test_over", forceOver);

    }

    //持续老化
    public boolean isKeepAging() {

        return AgingSharedPreference.getBoolean(getName() + "_keep_aging", false);

    }

    public void setKeepAging(boolean keep) {

        AgingSharedPreference.setBoolean(getName() + "_keep_aging", keep);

    }

    public boolean isTestOver() {
        if (isForceTestOver()) {
            return true;
        }

        if (isKeepAging()) {
            return false;
        }

        if (isCountForTestOver) {
            return getTestCount() >= getTimesOfTestOver();
        } else {
            if (getStartTime_ms() <= 0) {
                //小于0, 说明他重来没有设置过.即未 start 过
                return false;
            }

            return (AgingLongSettingsAttr.aging_time_tick.get() - getStartTime_ms()) >= getTimesOfTestOver();

        }
    }

    public void clear() {

        setLog("");
        setErrorLog("");

        setStartTime_ms(0);
        setExitTime_ms(0);

        setStartTimeAbsolute_ms(0);
        setExitTimeAbsolute_ms(0);

        setTestCount(0);
        setForceTestOver(false);
        setKeepAging(false);

    }

    public AgingTestItemBase getAgingTestItem() {
        Class<? extends  AgingTestItemBase> cls = getItemCls();
        if (cls == null) {
            return null;
        }
        try {
            return cls.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }


    private static final ThreadLocal<SimpleDateFormat> SDF_THREAD_LOCAL = new ThreadLocal<>();

    @NonNull
    private static SimpleDateFormat getDefaultFormat() {
        SimpleDateFormat simpleDateFormat = SDF_THREAD_LOCAL.get();
        if (simpleDateFormat == null) {
            simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.getDefault());
            SDF_THREAD_LOCAL.set(simpleDateFormat);
        }
        return simpleDateFormat;
    }

    public static String now2String() {
        return getDefaultFormat().format(new Date());
    }

    public final static String PATH_AGING_DETAIL = FTUtils.getFTStorageDirectory() + File.separator + "aging";

    public static boolean agingHasDetail() {
        File agingFile = new File(PATH_AGING_DETAIL);

        if (!agingFile.exists()) {
            return false;
        }

        if (!agingFile.isDirectory()) {
            return false;
        }

        if (agingFile.list() == null) {
            return false;
        }

        if (agingFile.list().length <= 0) {
            return false;
        }

        return true;

    }

    public static List<File> getAgingDetailFiles() {
        List<File> fileList = new ArrayList<>();
        if (!agingHasDetail()) {
            return fileList;
        }
        File agingFile = new File(PATH_AGING_DETAIL);

        fileList.addAll(Arrays.asList(agingFile.listFiles()));

        Collections.sort(fileList, new Comparator<File>() {
            @Override
            public int compare(File o1, File o2) {
                return o2.compareTo(o1);
            }
        });

        return fileList;
    }

    public static void saveLog() {
        File agingFile = new File(PATH_AGING_DETAIL);
        if (!agingFile.exists()) {
            agingFile.mkdirs();
        }
        String suffix = "-fail";
        if (AgingBooleanSettingsAttr.aging_test_ok.get()) {
            suffix = "-ok";
        }
        String fileName = agingFile.getAbsolutePath() + File.separator + now2String() + suffix + ".log";

        final Context context = FTApplication.getContext();
        StringBuilder sb = new StringBuilder();

        String title = context.getString(R.string.aging_result_info);
        sb.append(title);

        String useTime = TimeStringUtils.makeTimeString(AgingLongSettingsAttr.aging_time_tick.get());
        String useTimeAbsolute = TimeStringUtils.makeTimeString(AgingLongSettingsAttr.aging_time_exit_absolute.get() - AgingLongSettingsAttr.aging_time_start_absolute.get());

        sb.append(context.getString(R.string.aging_result_use_time, useTime, useTimeAbsolute));

        for (AgingTestItemAttr attr : AgingTestItemAttr.values()) {
            boolean newLine = false;
            if (!TextUtils.isEmpty(attr.getTestDetail())) {
                sb.append(attr.getTestDetail());
                newLine = true;
            }
            if (!attr.isTestOver()) {
                sb.append("  ");
                sb.append(context.getString(R.string.aging_test_item_not_over));
                sb.append(", ");
                sb.append(attr.getDetail());
            }

            if (newLine) {
                sb.append("\n");
            }
        }

        StringBuilder errorLogStringBuilder = new StringBuilder("");
        for (AgingTestItemAttr attr : AgingTestItemAttr.values()) {
            if (!TextUtils.isEmpty(attr.getErrorLog())) {
                errorLogStringBuilder.append(attr.getErrorLog());
                errorLogStringBuilder.append("\n");
            }
        }
        if (!TextUtils.isEmpty(errorLogStringBuilder.toString())) {
            sb.append("=========error Log==================\n");
            sb.append(errorLogStringBuilder.toString());
            sb.append("=========error Log==================\n");
        }

        StringBuilder errorStringBuilder = new StringBuilder("");
        StringBuilder countStringBuilder = new StringBuilder("");

        //show hardware log
        for (AgingHardwareItemAttr attr : AgingHardwareItemAttr.values()) {
            if (!TextUtils.isEmpty(attr.getErrorLog())) {
                errorStringBuilder.append(attr.getErrorLog());
                errorStringBuilder.append("\n");
            }
            if (!TextUtils.isEmpty(attr.getItemCountString())) {
                countStringBuilder.append(attr.getItemCountString());
                countStringBuilder.append("\n");
            }
        }

        sb.append(countStringBuilder.toString());

        if (!TextUtils.isEmpty(errorStringBuilder.toString())) {
            sb.append("========error Log===================\n");
            sb.append(errorStringBuilder.toString());
            sb.append("========error Log===================\n");
        }


        FileReadWrite.writeAppendFile(fileName, sb.toString());
    }

    public static void clearAgingAll() {

        for (AgingTestItemAttr attr : AgingTestItemAttr.values()) {
            attr.clear();
        }

        for (AgingBooleanSettingsAttr attr : AgingBooleanSettingsAttr.values()) {
            attr.clear();
        }

        for (AgingLongSettingsAttr attr : AgingLongSettingsAttr.values()) {
            attr.clear();
        }

        for (AgingHardwareItemAttr attr : AgingHardwareItemAttr.values()) {
            attr.clear();
        }

    }


}
